﻿using Sustainalytics.LongRunningTaskManager.Interface;
using System.Collections.Generic;
using System.IO;

namespace Sustainalytics.LongRunningTaskManager
{
    /// <summary>
    /// Task result as a file stored on disk.
    /// </summary>
    public class LongRunningTaskFileOnDiskResult : ILongRunningTaskResult, IEqualityComparer<LongRunningTaskFileOnDiskResult>
    {
        /// <summary>
        /// Task result type.
        /// </summary>
        public LongRunningTaskResultTypeEnum Type
        {
            get { return LongRunningTaskResultTypeEnum.FileOnDisk; }
        }

        /// <summary>
        /// Content Length.
        /// </summary>
        public long ContentLength { get; set; }

        /// <summary>
        /// Preferred file name to be used instead of that from FilePath.
        /// </summary>
        public string FileName { get; set; }

        /// <summary>
        /// File path.
        /// </summary>
        public string FilePath { get; set; }

        /// <summary>
        /// MIME Type.
        /// </summary>
        public string MimeType { get; set; }


        /// <summary>
        /// Load current instance from LongRunningTaskFileInMemResult thus saving in-memory result to disk.
        /// </summary>
        /// <param name="result"> File in-memory result. </param>
        public static LongRunningTaskFileOnDiskResult FromFileInMemResult(string fileDirectory, LongRunningTaskFileInMemResult fileInMemRes)
        {
            if (string.IsNullOrEmpty(fileDirectory))
            {
                throw new FilePathNullOrEmptyException();
            }

            if (fileInMemRes == null)
            {
                throw new LongRunningTaskResultNullException();
            }

            string filePath = Path.Combine(fileDirectory, fileInMemRes.FileName);

            // get path file info
            FileInfo fileInfo = new FileInfo(filePath);

            // create directory if does not exist
            if (fileInfo.Directory.Exists == false)
            {
                fileInfo.Directory.Create();
            }

            // save file to disk
            using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
            {
                fs.Write(fileInMemRes.Contents, 0, fileInMemRes.Contents.Length);
            }

            // create file disk result instance
            LongRunningTaskFileOnDiskResult fileDiskResult = new LongRunningTaskFileOnDiskResult
            {
                ContentLength = fileInMemRes.Contents.Length,
                FileName = fileInMemRes.FileName,
                FilePath = fileDirectory,
                MimeType = fileInMemRes.MimeType
            };

            return fileDiskResult;
        }


        public bool Equals(ILongRunningTaskResult x, ILongRunningTaskResult y)
        {
            if (x == null && y == null)
                return true;

            if (x == null || y == null)
                return false;

            if (x.GetType() != typeof(LongRunningTaskFileOnDiskResult) || x.GetType() != y.GetType())
                return false;

            return this.Equals((LongRunningTaskFileOnDiskResult)x, (LongRunningTaskFileOnDiskResult)y);
        }

        public int GetHashCode(ILongRunningTaskResult obj)
        {
            return this.GetHashCode(obj);
        }


        public bool Equals(LongRunningTaskFileOnDiskResult x, LongRunningTaskFileOnDiskResult y)
        {
            if (x == null && y == null)
                return true;

            if (x == null || y == null)
                return false;

            return (x.ContentLength == y.ContentLength)
                && ((x.FilePath == null && y.FilePath == null) || x.FilePath == y.FilePath)
                && ((x.FileName == null || y.FileName == null) || x.FileName == y.FileName)
                && ((x.MimeType == null || y.MimeType == null) || x.MimeType == y.MimeType);
        }

        public int GetHashCode(LongRunningTaskFileOnDiskResult obj)
        {
            return 0;
        }
    }
}
